package impl

import (
	"fmt"
)

type maker func() abstractShoe

// ！工厂
//
// 由工厂作为对外接口，聚合了abstractShoe的实现
type factory struct {
	makers map[string]maker
}

// 如果要扩展abstractShoe的实现，必须增加新的分支，所以对修改是开放的，不符合开
// 闭原则，但使用公共方法构造了扩展组件类，
//
// 问题：如果取消统一的构造面factory，直接在客户端使用NewBasketballShoe，会让程
// 序符合开闭原则吗？这里必须存在factory，尽管扩展组件中存在New方法，但还是需要
// 收拢分散的实现，以及包装一些复杂的初始化逻辑
func NewFactory() *factory {
	return &factory{
		makers: map[string]maker{
			"football":   newFootballShoe,
			"basketball": newBasketballShoe,
		},
	}
}

func (f *factory) Make(shoeCategory string) (abstractShoe, error) {
	maker, ok := f.makers[shoeCategory]
	if !ok {
		return nil, fmt.Errorf("error type: %s", shoeCategory)
	}

	return maker(), nil
}

/* 以上方法使用map取代了这里的switch，避免分支过多时圈复杂度过高
func (f *factory) MakeShoe(shoeCategory string) (abstractShoe, error) {
	switch shoeCategory {
	case "football":
		return newFootballShoe(), nil
	case "basketball":
		return newBasketballShoe(), nil
	default:
		return nil, fmt.Errorf("error shoe type: %s", shoeCategory)
	}
}
*/
